package com.ndp.fb.mq.service.schedulerservice.adpublish;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.ndp.fb.config.ConfigCentre;
import com.ndp.fb.constant.CommonConstants;
import com.ndp.fb.constant.ConfigConst;
import com.ndp.fb.enums.publish.PublishStatus;
import com.ndp.fb.mongo.api.PublishCacheMongoService;
import com.ndp.fb.rdb.api.PublishBatchRdbService;
import com.ndp.fb.rdb.model.PublishBatch;
import com.ndp.fb.redis.model.AdCreativeLevel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by infi on 2015/3/17.
 */
@Component
public class PublishAdCreativeStatusScanService {
    private static Logger LOG = LoggerFactory.getLogger(PublishAdCreativeStatusScanService.class);
    @Reference
    private PublishBatchRdbService publishBathRdbService;
    @Autowired
    private PublishCacheMongoServiceFailover publishCacheMongoService;
    @Autowired
    private PublishCampaignService publishAdCampaignGroups;



    public void execute(final PublishBatch batch){
        Integer publish_outtime = ConfigCentre.getInteger(ConfigConst.MQ_SERVICES_PUBLISH_BATCH_MINUTE);
        if(isRedo(batch)){
            if (reDoTimeOut(batch, publish_outtime)) return;
        }else{
            if (publishTimeOut(batch, publish_outtime)) return;
        }

        String creativeCacheStr = publishCacheMongoService.findCacheBlockByType(batch.getId(), PublishCacheMongoService.CREATIVE);
        Map <String,AdCreativeLevel> creativeLevelMap= JSONObject.parseObject(creativeCacheStr,  new TypeReference<HashMap<String,AdCreativeLevel>>(){});
        int succeedCount=0;
        int failedCount=0;
        for (AdCreativeLevel adCreativeLevel : creativeLevelMap.values()) {
             if(adCreativeLevel.getStatus()== PublishStatus.SUCCEED.getCode())  succeedCount++;
             if(adCreativeLevel.getStatus()== PublishStatus.FAIL.getCode())      failedCount++;
        }
        Integer allAdCreativeCount = batch.getAllAdCreativeCount();
        if(failedCount== allAdCreativeCount){
            //所有的创意都失败了，不在继续创建，由于可能是上一次的失败，所以需要等5分钟，如果所有创意依然是失败，继续设置为批次失败
            if(batch.getRetryCnt()>0){
                long min = (new Date().getTime() - batch.getRetryTime().getTime()) /(5000*60);
                if(min>5)  publishBathRdbService.updatePublishFail(batch.getId(), CommonConstants.PUBLISH_FAIL);
            }else{
                publishBathRdbService.updatePublishFail(batch.getId(), CommonConstants.PUBLISH_FAIL);
            }
        }else if (succeedCount>0&&succeedCount== allAdCreativeCount) {
            //有成功又失败，继续创建广告
            LOG.info(batch + "开始创建AdCampaignGroup");
            publishAdCampaignGroups.publish(batch.getId(),null,null);
        }
    }

    /**
     * 检查创建超时 批次正在跑  跑了两个小时的 置为失败
     * @param batch
     * @param publish_outtime
     * @return
     */
    private boolean publishTimeOut(PublishBatch batch, Integer publish_outtime) {
        Long pubMin = (new Date().getTime() - batch.getCreateTime().getTime()) / 60000;
        if(pubMin.intValue() >  (publish_outtime == 0 ? 120 : publish_outtime))
        {
            LOG.error(">>>>>>>>>>这个批次广告创建了好几个小时了，置为失败。");
            publishBathRdbService.updatePublishFail(batch.getId(), CommonConstants.PUBLISH_FAIL);
            return true;
        }
        return false;
    }

    /**
     *
     */
    /**
     * 检查重试超时  批次重试两个小时的 置为失败
     * @param batch
     * @param publish_outtime
     * @return
     */
    private boolean reDoTimeOut(PublishBatch batch, Integer publish_outtime) {
        if(batch.getPublishStatus() == PublishStatus.REDO.getCode())
        {
            long pubMin = (new Date().getTime() - batch.getRetryTime().getTime()) / 60000;
            if(pubMin > (publish_outtime == 0 ? 120 : publish_outtime)) {
                LOG.error(">>>>>>>>>>这个批次广告重试了好几个小时了，置为失败。");
                publishBathRdbService.updatePublishFail(batch.getId(), CommonConstants.PUBLISH_FAIL);
                return true;
            }else{
                return false;
            }

        }
        return false;

    }

    /**
     * 本次是否是重试
     * @param batch
     * @return
     */
    private boolean isRedo(PublishBatch batch){
        return !(batch.getRetryCnt()==0&&batch.getRetryTime()==null);
    }

}
